function MSTab() {

        /**
    * Css prefix pointing to the main tab control class. Prefix + specific suffix will form className of
    * desired element.
    *
    * @private
    * @property cssPrefix
    * @type     String
    * @default  TabControl
    */
    this.cssPrefix = "Tab";
    
    /**
    * Tab dom object
    *
    * @private
    * @property  tabDom
    * @type      DOM
    * @default   null
    */
    this.tabDom = null;

    /**
    * Tab dom content object
    *
    * @private
    * @property  tabContentDom
    * @type      DOM
    * @default   null
    */
    this.tabContentDom = null;

    /**
    * Default tab width in pixels
    *
    * @private
    * @property  tabSize
    * @type      Number
    * @default   70
    */
    this.tabSize = 70;

    /**
    * Tab title string
    *
    * @private
    * @property  title
    * @type      String
    * @default   null
    */
    this.title = null;

    /**
    * Tab content description string
    *
    * @private
    * @property  description
    * @type      String
    * @default   null
    */
    this.description = null;

    /**
    * Active tab flag - if tab is an active tab, flag set to true
    *
    * @private
    * @property  active
    * @type      Boolean
    * @default   false
    */
    this.active = false;

    /**
    * Tab inner control
    *
    * @private
    * @property  control
    * @type      MessUIElement
    * @default   null
    */
    this.control = null;



    this.TAB_TOP_CSS_SUFFIX = "Top";
    this.TAB_BOTTOM_CSS_SUFFIX = "Bottom";
    this.TAB_LEFT_CSS_SUFFIX = "Left";
    this.TAB_RIGHT_CSS_SUFFIX = "Right";
    this.TAB_CONTENT_CSS_SUFFIX = "Content";
    this.EDGE1 = "Edge1";
    this.EDGE2 = "Edge2";
    this.MIDDLE = "Middle";
    this.TITLE = "Title";
    this.OFF = "Off";
    
}
MSTab.prototype = new MessUIElement();
MSTab.prototype.toString = function() { return "js.mess.ui.controls.tabview.MSTab"; };
MessUIElement.prototype.addTagMapping("tab", "MSTab");


    /**
    * Builds tab control. Performs any necessary initialization routines.
    *
    * @public
    * @method  build
    */
    MSTab.prototype.build = function() {
              
        // initialize control
        this.initControl();

        // build dom
        this.buildDOMObject();

        // attach event handlers
        this.attachEventHandlers();
    };

    /**
    * Attaches all necessary event handlers for tab control.
    *
    * @private
    * @method   attachEventHandlers
    */
    MSTab.prototype.attachEventHandlers = function() {

        // mouse down on tab
	    eventUtil.addEventHandler(this.tabDom.firstChild, "mousedown", MSTab.prototype.onMouseDownHandler);

        // mouse over handler
        eventUtil.addEventHandler(this.tabDom.firstChild, "mouseover", MSTab.prototype.onMouseOverHandler);

        // mouse out handler
        eventUtil.addEventHandler(this.tabDom.firstChild, "mouseout", MSTab.prototype.onMouseOutHandler);
    };

    /**
    *  MouseDown event handler
    *
    * @event
    * @method onMouseDownHandler
    */
    MSTab.prototype.onMouseDownHandler = function() {

		var oEvent = eventUtil.getEvent();
		var oSource = eventUtil.getSource(oEvent);

		var tab = null;
		var target = MSTab.prototype.objects.get(oSource.id);

        if (target instanceof MSTab) {
        // window receiving event
            tab = target;
        }

        if (tab !== null) {
        	tab.getParent().setActiveTab(tab);
            eventUtil.stopEvent(oEvent);
        }
    };

    /**
    *  MouseOver event handler
    *
    * @event
    * @method onMouseOverHandler
    */
    MSTab.prototype.onMouseOverHandler = function() {

		var oEvent = eventUtil.getEvent();
		var oSource = eventUtil.getSource(oEvent);

		var tab = null;
		var target = MSTab.prototype.objects.get(oSource.id);

        if (target instanceof MSTab) {
        // window receiving event
            tab = target;
        }

        if (tab !== null) {
            // on mouse over logic comes here

            // [1] update tab description for inactive tab
            if (!tab.isActive()) {
                tab.getParent().setTabDescription(tab.getDescription());
            }

            eventUtil.stopEvent(oEvent);
        }
    };

    /**
    *  MouseOut event handler
    *
    * @event
    * @method onMouseOutHandler
    */
    MSTab.prototype.onMouseOutHandler = function() {

        var oEvent = eventUtil.getEvent();
		var oSource = eventUtil.getSource(oEvent);

		var tab = null;
		var target = MSTab.prototype.objects.get(oSource.id);

        if (target instanceof MSTab) {
        // tab receiving event
            tab = target;
        }

        if (tab !== null) {
            // on mouse over logic comes here

            // [1] hide tab description for inactive tab
            if (!tab.isActive()) {
                tab.getParent().setTabDescription(null);
            }

            eventUtil.stopEvent(oEvent);
        }
    };

    /**
    * Builds DOM tab&content representation
    *
    * @private
    * @method  buildDOMObject
    */
    MSTab.prototype.buildDOMObject = function() {

        // build tab dom
        this.tabDom = this.buildTabDOM();

        // build content dom
        this.tabContentDom = this.buildTabContentDOM();
    };

    /**
    * Build tab dom
    *
    * @private
    * @method  buildTabDOM
    */
    MSTab.prototype.buildTabDOM = function() {

        var oDiv = DIV();
            oDiv.className = this.getTabCssClass();
            oDiv.id = this.getId();
            // inner tab
            var inner = DIV();
                inner.id = this.getId();
                inner.className = oDiv.className;
                // edge1
                var edge1 = DIV();
                    edge1.id = this.getId();
                    edge1.className = inner.className + this.EDGE1 + this.OFF;
                inner.appendChild(edge1);
                // middle part
                var middle = DIV();
                    middle.id = this.getId();
                    middle.className = inner.className + this.MIDDLE + this.OFF;
                    // tab title
                    var title = DIV();
                        title.id = this.getId();
                        title.className = inner.className + this.TITLE + this.OFF;
                        title.appendChild(TEXT(this.title));
                    middle.appendChild(title);
                inner.appendChild(middle);
                // edge2
                var edge2 = DIV();
                    edge2.id = this.getId();
                    edge2.className = inner.className + this.EDGE2 + this.OFF;
                inner.appendChild(edge2);

        oDiv.appendChild(inner);
        // disable text selection inside tab
        eventUtil.disableTextSelectionEvent(oDiv);

        if (this.parent.isHorizontal()) {
        // tab part of horizontal tab control

            // outer wrapper
            this.setWidth(this.tabSize+2, oDiv);
            this.setWidth(this.tabSize, inner);
            // inner tab
            this.setHeight(this.parent.getHeaderSize() - 4, oDiv);
            this.setHeight(this.parent.getHeaderSize() - 4, inner);
                // edge1
                this.setWidth(4, edge1);
                this.setHeight(this.parent.getHeaderSize() - 4, edge1);
                // middle
                this.setWidth(this.tabSize - 8, middle);
                this.setHeight(this.parent.getHeaderSize() - 4, middle);
                // edge 2
                this.setWidth(4, edge2);
                this.setHeight(this.parent.getHeaderSize() - 4, edge2);
        }
        else {
        // tab part of vertical tab control
            //[todo: ]    
        }


        //
        return oDiv;
    };

    MSTab.prototype.getTabCssClass = function() {

        if (this.parent.isHorizontal()) {
        // tab part of horizontal tab control
            if (this.parent.isHeaderFirst()) {
                return this.getCssPrefix() + this.TAB_TOP_CSS_SUFFIX;
            }
            else {
                return this.getCssPrefix() + this.TAB_BOTTOM_CSS_SUFFIX;
            }
        }
        else {
        // tab part of vertical tab control
            if (this.parent.isHeaderFirst()) {
                return this.getCssPrefix() + this.TAB_LEFT_CSS_SUFFIX;
            }
            else {
                return this.getCssPrefix() + this.TAB_RIGHT_CSS_SUFFIX;
            }
        }
    }

    /**
    * Build tab content dom
    *
    * @private
    * @method   buildTabContentDOM
    */
    MSTab.prototype.buildTabContentDOM = function() {

        var content = DIV();
            content.className = this.getTabContentCssClass();

        // update content dimensions
        this.setHeight(this.parent.getControlContentHeight(), content);
        this.setWidth(this.parent.getControlContentWidth(), content);
        
        return content;
    };

    MSTab.prototype.getTabContentCssClass = function() {

        return this.getCssPrefix() + this.TAB_CONTENT_CSS_SUFFIX;    
    };

    /**
    * Build tab child controls
    *
    * @public
    * @method  buildChildControls
    */
    MSTab.prototype.buildChildControls = function() {

        // [todo: build any tab-related child controls]
        
        // build child control
        this.buildChildControl();
    };

    /**
	 * Build child control if it has any
	 *
	 * @private
	 * @method  buildChildControl
	 */
	MSTab.prototype.buildChildControl = function() {

        if (this.control !== null) {

            // init parent and theme, build object
            this.buildChildControlObject(this.control);
            // update dom tree
	        this.tabContentDom.appendChild( this.control.render() );
            // try building control children
            try {
                this.control.buildChildControls();
            }
            catch (ex) {}
        }

        return this.control;
	};

    /**
    * Renteder tab dom object
    *
    * @public
    * @method  renderTab
    * @return  DOM
    */
    MSTab.prototype.renderTab = function() {
                       
        return this.tabDom;
    };

    /**
    * Render tab content dom object
    *
    * @public
    * @method   renderTabContent
    * @return   DOM
    */
    MSTab.prototype.renderTabContent = function() {

        return this.tabContentDom;
    }

    /**
    * tabSize property getter
    *
    * @public
    * @method  getTabSize
    * @return  {Number}
    */
    MSTab.prototype.getTabSize = function() {

        return this.tabSize;
    };

    /**
    * tabSize property setter
    *
    * @public
    * @method  setTabSize
    */
    MSTab.prototype.setTabSize = function(size) {

        this.tabSize = size;    
    };

    /**
    * tab title property setter
    *
    * @public
    * @method  setTitle
    * @param   {String} title string to set
    */
    MSTab.prototype.setTitle = function(title) {

        this.title = title;
    };

    /**
    * tab title property getter
    *
    * @public
    * @method  getTitle
    * @return  {String} tab title string
    */
    MSTab.prototype.getTitle = function() {

        return this.title;    
    };

    /**
    * Tab activation logic - change appearance
    *
    * @public
    * @method  activate
    */
    MSTab.prototype.activate = function() {

        this.active = true;

        var inner = this.tabDom.firstChild;
        var edge1 = inner.childNodes[0];
        var middle = inner.childNodes[1];
        var title = middle.firstChild;
        var edge2 = inner.childNodes[2];

        // update css classes for tab building blocks
        inner.className = this.getTabCssClass();
            edge1.className = inner.className + this.EDGE1;
            middle.className = inner.className + this.MIDDLE;
            title.className = inner.className + this.TITLE;
            edge2.className = inner.className + this.EDGE2;

        // update content
        this.setWidth(this.parent.getControlContentWidth(), this.tabContentDom);
        this.setHeight(this.parent.getControlContentHeight(), this.tabContentDom);
        this.show(this.tabContentDom);

        // hide tab description
        this.parent.setTabDescription(null);
    };

    /**
    * Tab deactivation logic - change appearance
    *
    * @public
    * @method  deactivate
    */
    MSTab.prototype.deactivate = function() {

        this.active = false;

        var inner = this.tabDom.firstChild;
        var edge1 = inner.childNodes[0];
        var middle = inner.childNodes[1];
        var title = middle.firstChild;
        var edge2 = inner.childNodes[2];

        // update css classes for tab building blocks
        inner.className = this.getTabCssClass();
            edge1.className = inner.className + this.EDGE1 + this.OFF;
            middle.className = inner.className + this.MIDDLE + this.OFF;
            title.className = inner.className + this.TITLE + this.OFF;
            edge2.className = inner.className + this.EDGE2 + this.OFF;

        // hide content
        this.hide(this.tabContentDom);
    };

    /**
    * Tab description property setter
    *
    * @public
    * @method  setDescription
    * @param   {String} desc to set
    */
    MSTab.prototype.setDescription = function(desc) {

        this.description = desc;
    };

    /**
    * Tab description property getter
    *
    * @public
    * @method  getDescription
    * @return  {String} desc
    */
    MSTab.prototype.getDescription = function() {

        return this.description;
    };

    /**
    * active flag property getter
    *
    * @public
    * @method  isActive
    * @return  {Boolean} active flag
    */
    MSTab.prototype.isActive = function() {

        return this.active;    
    };

    /**
    * Add child control to tab control
    *
    * @public
    * @method  addControl
    * @param   {MessUIElement} control   child control to add
    */
    MSTab.prototype.addControl = function(control) {

        this.control = control;
    };

    /**
    * Return content container height
    *
    * @public
    * @method  getControlContentHeight
    * @return  {Number} height in px of window content height
    */
    MSTab.prototype.getControlContentHeight = function() {

        return this.parent.getControlContentHeight();
    };

    /**
    * Return content container width
    *
    * @public
    * @method  getControlContentWidth
    * @return  {Number} width in px of window content width
    */
    MSTab.prototype.getControlContentWidth = function() {

        return this.parent.getControlContentWidth(); 
    };

    /**
    * Update tab width. Set width of content and of child control (can be recursive)
    *
    * @public
    * @method  setTabWidth
    * @param   {Number} width  width to set
    */
    MSTab.prototype.setTabWidth = function(width) {

        this.setWidth(width, this.tabContentDom);

        if (this.control !== null) {
        // update child control
            this.control.setControlWidth(width);
        }
    };

    /**
    * Update tab height. Set height of content and of child control (can be recursive)
    *
    * @public
    * @method  setTabHeight
    * @param   {Number} height  height to set
    */
    MSTab.prototype.setTabHeight = function(height) {

        this.setHeight(height, this.tabContentDom);

        if (this.control !== null) {
        // update child control
            this.control.setControlHeight(height);
        }
    }

    /**
    * Tab closing routine
    *
    * @public
    * @method  close
    */
    MSTab.prototype.close = function() {

        if (this.control) {
            this.control.destroy();
        }

        this.parent.closeTab(this);
    }

    /**
    * Tab closing routing (recursive)
    *
    * @public
    * @method  closeTab
    */
    MSTab.prototype.closeTab = function() {

        if (this.control) {
            this.control.close();
        }
        else {
            this.parent.closeTab(this);
        }
    };

    /**
    * Tab-specific destroyment logic
    *
    * @public
    * @method  destroy
    */
    MSTab.prototype.destroy = function() {

        // remove self from tabcontrol dom branches
        this.tabDom.parentNode.removeChild(this.tabDom);
        this.tabContentDom.parentNode.removeChild(this.tabContentDom);

        // garbage-collect instance
        gc.collect(this);
    };